#include "common.h"
#include "Timestamp.h"
#include "Streams.h"

using namespace esda;

int stringToInt(string s)
{
	istringstream istr(s);
	int i;
	istr >> i;
	return i;
}

double compareStreams(double leftInputValue, double rightInputValue)
{
	return leftInputValue == rightInputValue;
}

int main(int argc, char **argv)
{
	if (argc != 4) {
		DEBUG("Wrong number of arguments (" << argc << " found)\nUsage: " << argv[0] << " DATABASE APACHE-LOG NUMBER-OF-LINES");
		
		return 1;
	}
	
	// TODO : Il faudrait vider la db au préalable !
	
	string
		databaseName(argv[1]),
		requestStreamName("apacheLog_request"),
		answerStreamName("apacheLog_answer"),
		ligne;
	
	int numberOfLines = stringToInt(argv[3]), milestones = numberOfLines / 30;
	
	SQLiteStream<string> requestStream(databaseName, requestStreamName);
	SQLiteStream<double> answerStream(databaseName, answerStreamName);
	UnaryOperatorStream_Shift shiftedAnswerStream(answerStream, -200);
	UnaryOperatorStream_Timeshift timeshiftedAnswerStream(answerStream, (long long int) -86400000L);
	UnaryOperatorStream_Shift shiftedTimeShiftedAnswerStream((Stream<double> &) timeshiftedAnswerStream, -200);
	
	BinaryOperatorStream_UserFunc binaryUserFuncComparisonStream(shiftedAnswerStream, shiftedTimeShiftedAnswerStream, compareStreams);
	
	// On ouvre le fichier de logs
	ifstream logFile(argv[2]);
	
	Timestamp t, timeToGet = NULL;
	int i = 0;
	string s;
	double r;
	
	while (i < numberOfLines && getline(logFile, ligne)) {
		istringstream istr(ligne);
		
		string trash, date, request, answer;
		
		getline(istr, trash, '[');
		getline(istr, date, ']');
		getline(istr, trash, '"');
		getline(istr, request, '"');
		istr.get();
		getline(istr, answer, ' ');
		
		// On saute les lignes qui vont générer des requêtes invalides.
		if (request.find("'", 0) != string::npos) {
			continue;
		}
		
		// On détermine le Timestamp de la ligne (nouveau Timestamp)
		struct tm tstr;
		
		strptime(date.c_str(), "%d/%b/%Y:%T", &tstr);
		
		// On utilise i pour être certains de ne pas insérer plusieurs fois sur une même valeur de temps
		t = ((Timestamp::inttype) timegm(&tstr)) * ((Timestamp::inttype) 1000L) + ((Timestamp::inttype) (++i % 1000));
		
		// On insère la ligne dans le stream (nouveau StringValue, stream.set(time, value))
		
		s = request;
		requestStream.set(t, s);
		
		r = stringToInt(answer);
		answerStream.set(t, r);
		
		if (i % milestones == 0) {
			DEBUG(" (" << i << ") : " << t << " - " << r);
			
			// On récupère la valeur qu'on vient d'afficher
			
			TIME(timeStreamGet, double shiftedValue = shiftedAnswerStream.get(t));
			
			DEBUG(" Retrieved : " << shiftedValue);
		}
	}
	
	// On affiche l'intervalle de temps des logs
	
	DEBUG("stream.getFirstStart() = " << requestStream.getFirstStart());
	DEBUG("stream.getLastEnd() = " << requestStream.getLastEnd());
	
	return 0;
}
